package com.yfbao.horizon.encrypt.utils;


import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;

import java.io.UnsupportedEncodingException;
import java.security.Security;

/**
 * SM3加密与验证工具类
 * 国产哈希,不可逆算法
 */
@Slf4j
public class SM3Utils {

    private static final String EN_CODING = "UTF-8";

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 加密
     *
     * @param clearText 明文
     * @return
     */
    public static String encrypt(String clearText) {
        return encrypt(clearText.getBytes());
    }

    /**
     * 加密
     *
     * @param clearText
     * @return
     */
    public static String encrypt(byte[] clearText) {
        return Hex.toHexString(encrypt2Byte(clearText));
    }

    /**
     * 加密
     *
     * @param clearText
     * @return
     */
    public static byte[] encrypt2Byte(byte[] clearText) {
        SM3Digest sm3 = new SM3Digest();
        sm3.update(clearText, 0, clearText.length);
        byte[] encryptByte = new byte[sm3.getDigestSize()];
        sm3.doFinal(encryptByte, 0);
        return encryptByte;
    }

    /**
     * 加密
     *
     * @param clearText 明文
     * @param key       密钥
     * @return
     */
    public static String encrypt(String clearText, String key) {
        try {
            return encrypt(clearText.getBytes(EN_CODING), key);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * SM3加密方式之： 根据自定义密钥进行加密，返回加密后长度为32位的16进制字符串
     *
     * @param clearText 源数据
     * @param key       密钥
     * @return
     */
    public static String encrypt(byte[] clearText, String key) {
        return Hex.toHexString(encrypt2Byte(clearText, key));
    }

    /**
     * SM3加密方式之： 根据自定义密钥进行加密，返回加密后长度为32位的16进制字符串
     *
     * @param clearText 源数据
     * @param key       密钥
     * @return
     */
    public static byte[] encrypt2Byte(byte[] clearText, String key) {
        try {
            byte[] keyByte = key.getBytes(EN_CODING);
            KeyParameter keyParameter = new KeyParameter(keyByte);
            SM3Digest sm3 = new SM3Digest();
            HMac hMac = new HMac(sm3);
            hMac.init(keyParameter);
            hMac.update(clearText, 0, clearText.length);
            byte[] result = new byte[hMac.getMacSize()];
            hMac.doFinal(result, 0);
            return result;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
